package adventure.placeable.trigger;

import adventure.placeable.trigger.results.TriggerResult;
import java.util.ArrayList;

import adventure.placeable.PlaceableImp;
import player.Player;
import adventure.room.RoomManager;
import server.util.Broadcaster;
import server.util.BroadcasterImp;

/**
 *
 * @author Michael Hanns
 *
 */
public class TriggerImp extends PlaceableImp implements Trigger, TriggerEdit, Cloneable {

    private ArrayList<TriggerResult> results;
    private String triggeredName;
    private boolean limitedUses;
    private int totalUses;
    
    private Broadcaster out;

    public TriggerImp() {
        super();
        results = new ArrayList<TriggerResult>();
        triggeredName = "";
        limitedUses = false;
        totalUses = 0;
        this.out = new BroadcasterImp();
    }

    public TriggerImp(int id) {
        super(id);
        results = new ArrayList<TriggerResult>();
        triggeredName = "";
        limitedUses = false;
        totalUses = 0;
        this.out = new BroadcasterImp();
    }
    
    @Override
    public void setBroadcaster(Broadcaster broadcaster) {
        this.out = broadcaster;
    }

    @Override
    public void setTriggeredName(String name) {
        this.triggeredName = name;
    }

    @Override
    public void setLimitedUses(boolean val) {
        this.limitedUses = val;
    }

    @Override
    public void setTotalUses(int val) {
        this.totalUses = val;
    }

    @Override
    public String getName() {
        if (allResultsTripped()) {
            return triggeredName;
        } else {
            return super.getName();
        }
    }

    @Override
    public String getStandardName() {
        return super.getName();
    }

    @Override
    public String getTriggeredName() {
        return triggeredName;
    }

    @Override
    public boolean limitedUses() {
        return limitedUses;
    }

    @Override
    public int getTotalUses() {
        return totalUses;
    }

    @Override
    public TriggerResult[] getResults() {
        TriggerResult[] triggers = new TriggerResult[results.size()];
        for (int x = 0; x < results.size(); x++) {
            triggers[x] = results.get(x);
        }
        return triggers;
    }

    @Override
    public void addResult(TriggerResult t) {
        results.add(t);
    }

    @Override
    public boolean editResult(TriggerResult t, int position) {
        if (position > results.size()) {
            return false;
        } else {
            results.add(position, t);
            results.remove(position + 1);
            return true;
        }
    }

    @Override
    public void moveResultUp(int position) {
        if (position > 0) {
            TriggerResult temp = results.get(position - 1);
            results.set(position - 1, results.get(position));
            results.set(position, temp);
        }
    }

    @Override
    public void moveResultDown(int position) {
        if (position < results.size() - 1) {
            TriggerResult temp = results.get(position + 1);
            results.set(position + 1, results.get(position));
            results.set(position, temp);
        }
    }

    @Override
    public void moveConditionUp(int resultPos, int condPos) {
        results.get(resultPos).moveConditionUp(condPos);
    }

    @Override
    public void moveConditionDown(int resultPos, int condPos) {
        results.get(resultPos).moveConditionDown(condPos);
    }

    @Override
    public void removeResultAtIndex(int x) {
        if (x < results.size()) {
            results.remove(x);
        }
    }

    @Override
    public String tripTriggers(RoomManager r, Player p, String input) {
        String returnText = "";

        if (!allResultsTripped()) {
            String output = "";
            if (results.get(0).stillLive()) {
                output = results.get(0).executeResult(r, p, input, false, out);
                if (output.length() > 0) {
                    returnText = returnText + "\n" + output;
                }
            }

            for (int x = 1; x < results.size(); x++) {
                if (results.get(x).stillLive()) {

                    if (output.length() > 0) {
                        output = results.get(x).executeResult(r, p, input, false, out);
                    } else {
                        output = results.get(x).executeResult(r, p, input, true, out);
                    }

                    if (output.length() > 0) {
                        returnText = returnText.concat("\n".concat(output));
                    }
                }
            }
            if (returnText.length() > 0) {
                totalUses--;
            }
        }

        return returnText;
    }

    private boolean allResultsTripped() {
        if ((limitedUses && totalUses > 0) || !limitedUses) {
            if (results.size() > 0) {
                for (int x = 0; x < results.size(); x++) {
                    if (results.get(x).stillLive()) {
                        return false;
                    }
                }
                return true;
            } else {
                return true;
            }
        } else {
            return true;
        }
    }

    @Override
    public Trigger cloneThis() {
        Trigger newClone = new TriggerImp();
        try {
            newClone = (TriggerImp) this.clone();
            ((TriggerEdit)newClone).setBroadcaster(out);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return newClone;
    }

    @Override
    public Object clone() {
        try {
            Object clone = super.clone();
            ((TriggerImp) clone).results = new ArrayList<TriggerResult>();

            for (int c = 0; c < results.size(); c++) {
                ((TriggerImp) clone).results.add(results.get(c).cloneThis());
            }

            return clone;
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return null;
    }
}
